package org.vectrics.skill;


import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.log4j.Category;
import org.vectrics.common.db.CodedObject;
import org.vectrics.common.db.OwnedObject;
import org.vectrics.common.tree.Node;
import org.vectrics.common.tree.TreeNode;
import org.vectrics.domain.Domain;


public class Skill implements Serializable, Node, OwnedObject, CodedObject {
	public static int CONJUNCTION_ADDITIVE = 0;
	public static int CONJUNCTION_MAXIMUM = 1;
	
	public static String ROOT_SKILL_CODE = "root";

	
	public static String LEVEL_YES = "y";
	public static String LEVEL_NO = "n";
	
	static private Category log = Category.getInstance(Skill.class);
	static public String ROOT_CODE = "root";
	private String code = "";
	private String description = "";
	private boolean needsRating = true;
	private boolean section = false;
	private int childIndex = 0;
	private boolean voided = false;
	private Skill parent = null;
	private Set children = new HashSet();
	private SkillScoringMethod scoringMethod = null;
	private Set scoringLevels = new HashSet();
	private int conjunction = Skill.CONJUNCTION_ADDITIVE;
	private Long additiveDecay = new Long(0);
	private long weight = 100;
	private Domain domain = null;
	
	public Skill() {
	}

	public Skill(Skill parent, String code, String desc) {
		setCode(code);
		setDescription(desc);
	}

	public String getHierarchy() {
	    return(getSkillParent().getHierarchy() + "." + getCode());
	}

	public void copy(Skill other) {
		code = other.getCode();
		description = other.getDescription();
		this.setSkillParent(other.getSkillParent());
		this.scoringMethod = other.getScoringMethod();
	}

	static public void setMasterSkillSet(SkillSet iMasterSet)
	{
		//masterSkillSet = iMasterSet;
	};

    
	public void setDescription(String iDesc) {
		description = iDesc;
	};

	public String getDescription()
	{
		return(description);
	};
	public void setId(String id) {
		setCode(id);
	}
    
	public void setCode(String iCode)  {
			code = iCode;
	}

	public String getCode()
	{
		return(code);
	}


	public String getId() {
		return(getCode());
	}


	/**
	 * @return Returns the parent.
	 */
	public Skill getSkillParent() {
		return parent;
	}
	/**
	 * @param parent The parent to set.
	 */
	public void setSkillParent(Skill parent) {
		this.parent = parent;
	}
	
	public Node getParent() {
	    return(parent);
	}
	
	/**
	 * @return Returns the needsRating.
	 */
	public boolean getNeedsRating() {
		return needsRating;
	}
	
	/**
	 * @param needsRating The needsRating to set.
	 */
	public void setNeedsRating(boolean needsRating) {
		this.needsRating = needsRating;
	}
	
/*
	public Collection getChildren() {
		log.debug("getChildren() called.");
        
		if (childrenDirty == true) {
			childrenDirty = false;
			if (log.isDebugEnabled())
				log.debug("getChildren() - finding children for skill: " + getSkillCode());
			Iterator iter = getTree().getMasterList().iterator();
			log.debug("getChildren() - looking at each skill on master list to see which are children of this skill.");
			while (iter.hasNext()) {
				Skill skill = (Skill)iter.next();
				if (skill.getParentCode() != null) {
					if (skill.getParentCode().equals(getSkillCode())) {
						addChild(skill);

						if (log.isDebugEnabled())   
							log.debug("getChildren() - " + skill.getDescription() + "  - added as child to: "
									+ getDescription());
					}
					else { 
						if (log.isDebugEnabled())   
							log.debug("getChildren() - rejected skill: " + skill.getSkillCode() + " parentCode = " + skill.getParentCode());
					}
				}
				else {
					if (log.isDebugEnabled())   
						log.debug("getChildren() - rejected skill: " + skill.getSkillCode() + " parentCode = null");
				}
			};

		}
		log.debug("getChildren() done.");
		return(super.getChildren());
	};
*/



	/**
	 * @return Returns the section.
	 */
	public boolean getSection() {
		return section;
	}

	/**
	 * @param section The section to set.
	 */
	public void setSection(boolean section) {
		this.section = section;
	}

	/**
	 * @return Returns the childIndex.
	 */
	public int getChildIndex() {
		return childIndex;
	}

	/**
	 * @param childIndex The childIndex to set.
	 */
	public void setChildIndex(int childIndex) {
		this.childIndex = childIndex;
	}

    /**
     * @return Returns the voided.
     */
    public boolean getVoided() {
        return voided;
    }
    
    /**
     * @param voided The voided to set.
     */
    public void setVoided(boolean voided) {
        this.voided = voided;
    }
    
    /**
     * @return Returns the children.
     */
    public Set getChildren() {
        return children;
    }
    
    /**
     * @param children The children to set.
     */
    public void setChildren(Set children) {
        this.children = children;
    }
    
    public void addChild(Node child) {
        this.getChildren().add(child);
        Skill childSkill = (Skill)child;
        childSkill.setSkillParent(this);
    }
    
	/**
	 * @return Returns the scoringMethod.
	 */
	public SkillScoringMethod getScoringMethod() {
		return scoringMethod;
	}
	/**
	 * @param scoringMethod The scoringMethod to set.
	 */
	public void setScoringMethod(SkillScoringMethod scoringMethod) {
		this.scoringMethod = scoringMethod;
	}
	
	
	/**
	 * @return Returns the scoringLevels.
	 */
	public Set getScoringLevels() {
		return scoringLevels;
	}
	
	/**
	 * @param scoringLevels The scoringLevels to set.
	 */
	public void setScoringLevels(Set scoringLevels) {
		this.scoringLevels = scoringLevels;
	}
	
	public boolean hasLevelsForScoringMethod(SkillScoringMethod scoringMethod) {
		boolean found = false;
		Iterator iter = this.scoringLevels.iterator();
		while (iter.hasNext()) {
			SkillScoringMethodLevel scoreLevel = (SkillScoringMethodLevel)iter.next();
			if (scoreLevel.getSkillScoringMethod().getCode().equals(scoringMethod.getCode())) {
				found = true;
			}
		}
		return(found);
	}
	
	public Long getAdditiveDecay() {
		return additiveDecay;
	}
	
	public void setAdditiveDecay(Long additiveDecay) {
		this.additiveDecay = additiveDecay;
	}
	
	
	/**
	 * @return Returns the conjunction.
	 */
	public int getChildConjunctionType() {
		return conjunction;
	}
	/**
	 * @param conjunction The conjunction to set.
	 */
	public void setChildConjunctionType(int conjunction) {
		this.conjunction = conjunction;
	}
	
	/**
	 * @return Returns the weight.
	 */
	public long getWeight() {
		return weight;
	}
	/**
	 * @param weight The weight to set.
	 */
	public void setWeight(long weight) {
		this.weight = weight;
	}

	/**
	 * @return Returns the domain.
	 */
	public Domain getDomain() {
		return domain;
	}

	/**
	 * @param domain The domain to set.
	 */
	public void setDomain(Domain domain) {
		this.domain = domain;
	}
	
	
	public String toString() {
		return("Skill|code=" + this.code + "|description" + this.description + "|weight" + this.weight);
	}
}
